part of '../dio.dart';

/// 如果请求失败，会自动报错
abstract class RestfulClient<T extends Identity> {
  /// url的前半段，比如"/pomos"，由API补齐后半段
  String get baseRoute;

  /// 需要一个已经有baseUrl、token的客户端
  Dio get client;

  /// 获取所有
  Future<List<T>> getAll();

  /// 获取单个内容，如果404则返回null
  Future<T?> findOne(int id);

  /// 使用新的对象
  Future<void> update(T object);

  /// 输入一系列参数，创建一个对象
  Future<T> create(Json args);

  /// 删除某个内容，
  Future<void> delete(int id);
}

/// 由于限制，暂时不知道怎么做测试，因此以后再补上好了
class RestfulClientGeneral<T extends Identity> implements RestfulClient {
  @override
  final String baseRoute;

  @override
  final Dio client;

  T Function(Json raw) unzip;

  RestfulClientGeneral({
    required this.baseRoute,
    required this.client,
    required this.unzip,
  }) {
    // 客户端需要有基础url和token，否则无法使用
    assert(client.options.baseUrl.isNotEmpty);
    // assert(client.options.headers["Authorization"] != null);
  }

  @override
  Future<T> create(Json args) async {
    final response = await client.post(baseRoute, data: args);
    final T object = unzip(response.data);
    return object;
  }

  @override
  Future<void> delete(int id) => client.delete("$baseRoute/$id");

  @override
  Future<T?> findOne(int id) async {
    try {
      final response = await client.get("$baseRoute/$id");
      final T obj = unzip(response.data);
      return obj;
    } catch (e) {
      // 如果是找不到，则返回null
      if (e is DioException && e.response?.statusCode == 404) return null;
      // 如果其他原因则继续报错
      rethrow;
    }
  }

  @override
  Future<List<T>> getAll() async {
    final response = await client.get(baseRoute);
    final JsonList bodyList = response.data;
    List<T> list = bodyList.unzip(unzip);
    return list;
  }

  @override
  Future<void> update(Identity object) =>
      client.put("$baseRoute/${object.id}", data: object.toJson());
}
